package cn.iocoder.yudao.module.apijson.service.access;

import apijson.RequestMethod;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.biz.system.roleaccess.RoleAccessCommonApi;
import cn.iocoder.yudao.framework.common.biz.system.roleaccess.dto.RoleAccessDTO;
import cn.iocoder.yudao.module.apijson.framework.service.ApiJsonService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.util.*;

import cn.iocoder.yudao.module.apijson.controller.admin.access.vo.*;
import cn.iocoder.yudao.module.apijson.dal.dataobject.access.AccessDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.apijson.dal.mysql.access.AccessMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.apijson.enums.ErrorCodeConstants.*;

/**
 * 权限配置(必须) Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class AccessServiceImpl implements AccessService {

    @Resource
    private AccessMapper accessMapper;
    @Resource
    private RoleAccessCommonApi roleAccessCommonApi;
    @Resource
    private ApiJsonService apiJsonService;

    @Override
    public Long createAccess(AccessSaveReqVO createReqVO) {
        // 插入
        AccessDO access = BeanUtils.toBean(createReqVO, AccessDO.class);
        accessMapper.insert(access);
        apiJsonService.reload("ACCESS");
        // 返回
        return access.getId();
    }

    @Override
    public void updateAccess(AccessSaveReqVO updateReqVO) {
        // 校验存在
        validateAccessExists(updateReqVO.getId());
        // 更新
        AccessDO updateObj = BeanUtils.toBean(updateReqVO, AccessDO.class);
        accessMapper.updateById(updateObj);
        apiJsonService.reload("ACCESS");
    }

    @Override
    public void deleteAccess(Long id) {
        // 校验存在
        validateAccessExists(id);
        // 删除
        accessMapper.deleteById(id);
        apiJsonService.reload("ACCESS");
    }

    @Override
    public void deleteAccessListByIds(List<Long> ids) {
        // 校验存在
        validateAccessExists(ids);
        // 删除
        accessMapper.deleteByIds(ids);
        apiJsonService.reload("ACCESS");
    }

    private void validateAccessExists(List<Long> ids) {
        List<AccessDO> list = accessMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(ACCESS_NOT_EXISTS);
        }
    }

    private void validateAccessExists(Long id) {
        if (accessMapper.selectById(id) == null) {
            throw exception(ACCESS_NOT_EXISTS);
        }
    }

    @Override
    public AccessDO getAccess(Long id) {
        return accessMapper.selectById(id);
    }

    @Override
    public PageResult<AccessDO> getAccessPage(AccessPageReqVO pageReqVO) {
        return accessMapper.selectPage(pageReqVO);
    }

    @Override
    public List<AccessAllDataRespVO> getAllAccess(AccessAllDataReqVO reqVO) {
        HashMap<String, Map<String, Boolean>> roleMap = new HashMap<>();
        List<AccessDO> accessDOList = accessMapper.selectList();
        for (AccessDO accessDO : accessDOList) {
            String alias = accessDO.getAlias();
            HashMap<String, Boolean> methodMap = new HashMap<>();
            for (String method : RequestMethod.ALL_NAME_LIST) {
                methodMap.put(method, false);
            }
            roleMap.put(alias, methodMap);
        }
        List<RoleAccessDTO> roleList = roleAccessCommonApi.getRoleAccessListByRoleId(reqVO.getRoleId());
        for (RoleAccessDTO roleAccessDTO : roleList) {
            String alias = roleAccessDTO.getAlias();
            if (roleMap.containsKey(alias)) {
                roleMap.get(alias).put(roleAccessDTO.getMethod(), true);
            }
        }
        List<AccessAllDataRespVO> accessAllDataRespVOList = new ArrayList<>();
        for (Map.Entry<String, Map<String, Boolean>> entry : roleMap.entrySet()) {
            AccessAllDataRespVO accessAllDataRespVO = new AccessAllDataRespVO();
            accessAllDataRespVO.setAlias(entry.getKey());
            accessAllDataRespVO.setMethods(entry.getValue());
            accessAllDataRespVOList.add(accessAllDataRespVO);
        }
        return accessAllDataRespVOList;
    }

}